package com.wolfsea.dottedlinedemo
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Rect
import android.util.AttributeSet
import android.util.Log
import android.view.View
import kotlinx.coroutines.*

/**
 *@desc DottedLineView
 *@author liuliheng
 *@time 2022/12/6  21:47
 **/
class DottedLineView @JvmOverloads constructor(
    context: Context,
    attributeSet: AttributeSet? = null
) : View(context, attributeSet), CoroutineScope by MainScope() {

    private val linePaint by lazy {
        Paint().apply {
            isAntiAlias = true
            isDither = true
            color = context.resources.getColor(R.color.purple_200)
        }
    }

    private val newLinePaint by lazy {
        Paint().apply {
            isAntiAlias = true
            isDither = true
            color = context.resources.getColor(R.color.teal_200)
        }
    }

    private val animationLinePaint by lazy {
        Paint().apply {
            isAntiAlias = true
            isDither = true
            color = context.resources.getColor(R.color.teal_700)
        }
    }

    private val lineRect by lazy {
        Rect()
    }

    private val lineTop = context.resources.getDimension(R.dimen.dp_30).toInt()
    private val lineBottom = lineTop + context.resources.getDimension(R.dimen.dp_1).toInt()

    private val newLineTop = context.resources.getDimension(R.dimen.dp_60).toInt()
    private val newLineBottom = newLineTop + context.resources.getDimension(R.dimen.dp_1).toInt()

    private val circlePaint by lazy {
        Paint().apply {
            isAntiAlias = true
            isDither = true
            style = Paint.Style.STROKE
            strokeWidth = context.resources.getDimension(R.dimen.dp_1)
            color = context.resources.getColor(R.color.purple_500)
        }
    }

    private val circlePaintArrays by lazy {
        arrayOf(
            Paint().apply {
                isAntiAlias = true
                isDither = true
                style = Paint.Style.STROKE
                strokeWidth = context.resources.getDimension(R.dimen.dp_1)
                color = context.resources.getColor(R.color.red)
            },
            Paint().apply {
                isAntiAlias = true
                isDither = true
                style = Paint.Style.STROKE
                strokeWidth = context.resources.getDimension(R.dimen.dp_1)
                color = context.resources.getColor(R.color.yellow)
            },
            Paint().apply {
                isAntiAlias = true
                isDither = true
                style = Paint.Style.STROKE
                strokeWidth = context.resources.getDimension(R.dimen.dp_1)
                color = context.resources.getColor(R.color.color_e91e63)
            },
            Paint().apply {
                isAntiAlias = true
                isDither = true
                style = Paint.Style.STROKE
                strokeWidth = context.resources.getDimension(R.dimen.dp_1)
                color = context.resources.getColor(R.color.color_00bcd4)
            },
            Paint().apply {
                isAntiAlias = true
                isDither = true
                style = Paint.Style.STROKE
                strokeWidth = context.resources.getDimension(R.dimen.dp_1)
                color = context.resources.getColor(R.color.color_8bc34a)
            },
            Paint().apply {
                isAntiAlias = true
                isDither = true
                style = Paint.Style.STROKE
                strokeWidth = context.resources.getDimension(R.dimen.dp_1)
                color = context.resources.getColor(R.color.color_009688)
            },
            Paint().apply {
                isAntiAlias = true
                isDither = true
                style = Paint.Style.STROKE
                strokeWidth = context.resources.getDimension(R.dimen.dp_1)
                color = context.resources.getColor(R.color.black)
            }
        )
    }

    private val colorCircleMap by lazy {
        mutableMapOf<Int, Float>()
    }

    private val antiColorCircleMap by lazy {
        mutableMapOf<Int, Float>()
    }

    private val colorIndexArr = IntArray(TOTAL_ANGLE / (ARC_WIDTH + ARC_SPACE))

    private var circleIndex = 0

    private var lineCountIndex = 0
    private var newLineRight = 0

    private var job: Job? = null

    override fun onFinishInflate() {
        super.onFinishInflate()
        for (i in colorIndexArr.indices) {
            colorIndexArr[i] = i
        }

        job = launch(Dispatchers.IO) {
            delay(2000)
            lineCountIndex = 1
            while (true) {
                circleIndex++

                colorIndexArr[0]++
                for (i in 1.until(colorIndexArr.size)) {
                    colorIndexArr[i] = colorIndexArr[i - 1] + 1
                }

                newLineRight += 8
                if (newLineRight == LINE_WIDTH) {
                    lineCountIndex++
                    newLineRight = 0
                }
                delay(1000)
                invalidate()
            }
        }
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        val viewWidth = context.resources.displayMetrics.widthPixels - paddingStart - paddingEnd
        val viewHeight = context.resources.displayMetrics.heightPixels - paddingTop - paddingBottom
        setMeasuredDimension(viewWidth, viewHeight)
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        canvas?.apply {
            /*
            * 绘制虚线
            * */
            val remainedWidth = measuredWidth % (LINE_WIDTH + LINE_SPACE)
            val lineCount = (measuredWidth - remainedWidth) / (LINE_WIDTH + LINE_SPACE)

            var space = 0
            for (i in 0.until(lineCount)) {
                lineRect.set(
                    LINE_WIDTH * i + space + remainedWidth / 2 + LINE_SPACE / 2,
                    lineTop,
                    LINE_WIDTH * (i + 1) + space + remainedWidth / 2 + LINE_SPACE / 2,
                    lineBottom
                )
                drawRect(lineRect, linePaint)
                space += LINE_SPACE
            }

            var newSpace = 0
            for (i in 0.until(lineCount)) {
                lineRect.set(
                    LINE_WIDTH * i + newSpace + remainedWidth / 2 + LINE_SPACE / 2,
                    newLineTop,
                    LINE_WIDTH * (i + 1) + newSpace + remainedWidth / 2 + LINE_SPACE / 2,
                    newLineBottom
                )
                drawRect(lineRect, newLinePaint)
                newSpace += LINE_SPACE
            }

            var animationSpace = 0
            for (i in 0.until(lineCountIndex)) {
                lineRect.set(
                    LINE_WIDTH * i + animationSpace + remainedWidth / 2 + LINE_SPACE / 2,
                    newLineTop,
                    if (i == lineCountIndex - 1) {
                        LINE_WIDTH * i + newLineRight + animationSpace + remainedWidth / 2 + LINE_SPACE / 2
                    } else {
                        LINE_WIDTH *(i + 1) + animationSpace + remainedWidth / 2 + LINE_SPACE / 2
                    },
                    newLineBottom
                )
                drawRect(lineRect, animationLinePaint)
                animationSpace += LINE_SPACE
            }

            if (lineCountIndex == lineCount + 1) {
                lineCountIndex = 1
            }

            /*
            * 绘制虚线圆
            * */
            val pieces = TOTAL_ANGLE / (ARC_WIDTH + ARC_SPACE)
            for (i in 0.until(pieces)) {
                val startAngle = i * (ARC_WIDTH + ARC_SPACE).toFloat()
                val sweepAngle = ARC_WIDTH.toFloat()
                drawArc(
                    0f,
                    (height - width) / 2.0f,
                    width.toFloat(),
                    (height - width) / 2.0f + width.toFloat(),
                    startAngle,
                    sweepAngle,
                    false,
                    circlePaint
                )
            }

            /*
            * 绘制七彩虚线圆
            * */
            val colorPieces = TOTAL_ANGLE / (ARC_WIDTH + ARC_SPACE)
            for (i in 0.until(colorPieces)) {
                val startAngle =
                    i * (ARC_WIDTH + ARC_SPACE).toFloat() + (ARC_WIDTH + ARC_SPACE) * circleIndex % TOTAL_ANGLE
                if (circleIndex == colorPieces) {
                    circleIndex = 0
                }
                val sweepAngle = ARC_WIDTH.toFloat()
                drawArc(
                    if (colorCircleMap[0] == null) {
                        colorCircleMap[0] = width / 4.0f
                        width / 4.0f
                    } else {
                        colorCircleMap[0]!!
                    },
                    if (colorCircleMap[1] == null) {
                        val value = (height - width) / 2.0f + width / 4.0f
                        colorCircleMap[1] = value
                        value
                    } else {
                        colorCircleMap[1]!!
                    },
                    if (colorCircleMap[2] == null) {
                        val value = width * 3.0f / 4.0f
                        colorCircleMap[2] = value
                        value
                    } else {
                        colorCircleMap[2]!!
                    },
                    if (colorCircleMap[3] == null) {
                        val value = (height - width) / 2.0f + width.toFloat() - width / 4.0f
                        colorCircleMap[3] = value
                        value
                    } else {
                        colorCircleMap[3]!!
                    },
                    startAngle,
                    sweepAngle,
                    false,
                    circlePaintArrays[i % circlePaintArrays.size]
                )
            }

            for (i in colorIndexArr.indices) {
                val startAngle =
                    -colorIndexArr[i] * (ARC_WIDTH + ARC_SPACE).toFloat()
                val sweepAngle = ARC_WIDTH.toFloat()
                drawArc(
                    if (antiColorCircleMap[0] == null) {
                        antiColorCircleMap[0] = width / 4.0f - 50f
                        width / 4.0f - 10f
                    } else {
                        antiColorCircleMap[0]!!
                    },
                    if (antiColorCircleMap[1] == null) {
                        val value = (height - width) / 2.0f + width / 4.0f - 50f
                        antiColorCircleMap[1] = value
                        value
                    } else {
                        antiColorCircleMap[1]!!
                    },
                    if (antiColorCircleMap[2] == null) {
                        val value = width * 3.0f / 4.0f + 50f
                        antiColorCircleMap[2] = value
                        value
                    } else {
                        antiColorCircleMap[2]!!
                    },
                    if (antiColorCircleMap[3] == null) {
                        val value = (height - width) / 2.0f + width.toFloat() - width / 4.0f + 50f
                        antiColorCircleMap[3] = value
                        value
                    } else {
                        antiColorCircleMap[3]!!
                    },
                    startAngle,
                    sweepAngle,
                    false,
                    circlePaintArrays[i % circlePaintArrays.size]
                )
            }
        }
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        job?.cancel()
    }

    companion object {
        const val TAG = "DottedLineView"

        //线宽
        const val LINE_WIDTH = 40

        //线间距
        const val LINE_SPACE = 10

        //总角度
        const val TOTAL_ANGLE = 360

        //弧宽
        const val ARC_WIDTH = 5

        //弧间距
        const val ARC_SPACE = 5
    }

}